package com.jboltai.capability.vdb.types.elasticsearch;

import cn.hutool.core.util.StrUtil;
import com.jboltai.capability.vdb.search.FilterOpt;
import com.jboltai.capability.vdb.search.VDBConditions;
import com.jboltai.capability.vdb.search.VDBFilter;
import com.jboltai.capability.vdb.types.tencent.FieldUtil;

import java.util.List;

public class SQLBuilder {
    public static String select(String tableName, VDBConditions conditions) {
        if (conditions == null) {
            return "SELECT * FROM " + tableName;
        }

        List<String> selectList = conditions.getSelect();

        // 模板
        String template = "SELECT %s FROM %s %s %s";

        String limitSQL = "";
        Integer limit = conditions.getLimit();
        if (limit != null && limit > 0) {
            limitSQL = "LIMIT " + limit;
        }

        // 列
        String columnSQL = buildColumnSQL(selectList);

        // 查询条件
        String conditionSQL = buildConditionSQL(conditions);

        return String.format(template, columnSQL, tableName, conditionSQL, limitSQL);
    }

    public static String buildColumnSQL(List<String> columnList) {
        if (columnList == null || columnList.isEmpty()) {
            return "*";
        }
        StringBuilder sb = new StringBuilder();
        for (String str : columnList) {
            String[] columnArr = str.split(",");
            for (String column : columnArr) {
                column = column.trim();
                if (StrUtil.isBlank(column)) {
                    continue;
                }
                sb.append(column).append(",");
            }
        }
        return sb.substring(0, sb.length() - 1);
    }

    private static String buildConditionSQL(VDBConditions conditions) {
        List<VDBFilter> filterList = conditions.getFilter();
        List<String> matchTextList = conditions.getMatchText();
        String matchText = "";
        if (matchTextList != null && !matchTextList.isEmpty()) {
            matchText = matchTextList.get(0);
        }

        StringBuilder condition = new StringBuilder();

        String link = "";
        if (StrUtil.isNotBlank(matchText)) {
            if (filterList != null && !filterList.isEmpty()) {
                condition.append("MATCH(doc,'" + matchText + "') AND ");
            } else {
                condition.append("MATCH(doc,'" + matchText + "')");
            }
        }

        for (VDBFilter filter : filterList) {
            String columnName = filter.getName();
            Object columnValue = filter.getValue();
            FilterOpt option = filter.getOpt();

            Boolean isPrimaryKey = columnName.equals("_id");

            if (isPrimaryKey) {
                switch (option) {
                    case EQ:
                        condition.append(columnName).append("=").append(formatValue(columnValue));
                        continue;
                    case IN:
                        condition.append(columnName).append(" in(").append(formatValue(columnValue)).append(")");
                        continue;
                    default:
                        throw new RuntimeException("主键不支持[" + option.name() + "]操作");
                }
            } else {
                if (link != null) {
                    condition.append(link);
                } else {
                    condition.append(" AND ");
                }

                switch (option) {
                    case AND:
                        link = " AND ";
                        continue;
                    case OR:
                        link = " OR ";
                        continue;
                    case AND_NOT:
                        link = " AND NOT ";
                        continue;
                    case OR_NOT:
                        link = " OR NOT ";
                        continue;
                    case BRACKET_LEFT:
                        link = "(";
                        continue;
                    case BRACKET_RIGHT:
                        link = ")";
                        continue;
                    case EQ:
                        condition.append(columnName).append("=").append(formatValue(columnValue));
                        break;
                    case NOT_EQ:
                        condition.append(columnName).append("!=").append(formatValue(columnValue));
                        break;
                    case GT:
                        condition.append(columnName).append(">").append(formatValue(columnValue));
                        break;
                    case GE:
                        condition.append(columnName).append(">=").append(formatValue(columnValue));
                        break;
                    case LT:
                        condition.append(columnName).append("<").append(formatValue(columnValue));
                        break;
                    case LE:
                        condition.append(columnName).append("<=").append(formatValue(columnValue));
                        break;
                    case IN:
                        condition.append(columnName).append(" in(").append(formatValue(columnValue)).append(")");
                        break;
                    case NOT_IN:
                        condition.append(columnName).append(" not in(").append(formatValue(columnValue)).append(")");
                        break;
                    default:
                        throw new RuntimeException("不支持[" + option + "]操作");
                }
                link = null;
            }
        }
        return "WHERE " + condition;
    }

    private static String formatValue(Object value) {
        String clazzType = value.getClass().getSimpleName();
        Boolean isArray = clazzType.contains("[]");
        Boolean isNumber = FieldUtil.isNumber(clazzType);

        if (isArray) {
            if (isNumber) {
                StringBuilder sb = new StringBuilder();
                Object[] values = (Object[]) value;
                for (Object v : values) {
                    sb.append(v.toString()).append(",");
                }
                return sb.substring(0, sb.length() - 1);
            } else {
                StringBuilder sb = new StringBuilder();
                Object[] values = (Object[]) value;
                for (Object v : values) {
                    sb.append("'").append(v.toString()).append("',");
                }
                return sb.substring(0, sb.length() - 1);
            }
        } else {
            if (isNumber) {
                // 非数组, 数字
                return value.toString();
            } else {
                // 非数组, 非数字
                return "'" + value + "'";
            }
        }
    }
}
